#include "gate_listener_impl.h"
#include "gate_listener_event_handler.h"
#include "gate_client_session.h"
#include <map>
#include <set>

namespace utility
{
namespace network
{
gate_listener_impl::gate_listener_impl(net_module * netmodule)
{
    if (listener_ = netmodule->create_listener())
        listener_->set_session_mgr(this);
}


gate_listener_impl::~gate_listener_impl(void)
{
    listener_ = NULL;
}

bool gate_listener_impl::initialize(session_mgr * mgr)
{
    session_mgr_ = mgr;
    if (listener_ == NULL)
        return false;
    
    return session_mgr_ != NULL;
}

bool gate_listener_impl::start(const char * ip_address, const char * port)
{
    if (listener_ == NULL)
        return false;
    return listener_->start(ip_address, port);
}

void gate_listener_impl::on_accept(utility::network::session * s)
{
    gate_listener_event_handler::pointer event_handler = (gate_listener_event_handler::pointer)(new gate_listener_event_handler(this));
    s->set_event_handler(event_handler);
    event_handler->set_session(s);
}

session_mgr * gate_listener_impl::get_session_mgr()
{
    return session_mgr_;
}

void gate_listener_impl::set_max_recv_buf_size( uint32 size )
{
    listener_->set_recv_buf_size(size);
}

void gate_listener_impl::broadcast( std::list<session *> sessions, void * message, size_t message_length )
{
    typedef std::set<gate_client_session *> TSessions;
    typedef std::map<gate_sub_session *, TSessions> TClientSessions;
    TClientSessions client_sessions;

    std::list<session *>::iterator i = sessions.begin();
    for (; i != sessions.end(); i++)
    {
        gate_client_session * client_session = dynamic_cast<gate_client_session *>(*i);
        if (client_session)
        {
            gate_sub_session * sub_session = client_session->get_sub_session();
            TClientSessions::iterator j = client_sessions.find(sub_session);
            if (j == client_sessions.end())
                client_sessions.insert(std::make_pair(sub_session, TSessions()));
            client_sessions[sub_session].insert(client_session);
        }
    }

    TClientSessions::iterator j = client_sessions.begin();
    for ( ; j != client_sessions.end(); j++)
    {
        j->first->broadcast(j->second, message, message_length);
    }
}

}
}


